package com.weareint.common.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.weareint.common.beans.ServiceBeans;
import com.weareint.common.constants.Constants;
import com.weareint.common.dto.AbstractDTO;
import com.weareint.common.entity.AbstractEntity;
import org.slf4j.Logger;

import java.util.*;
import java.util.stream.Collectors;

/**
 *
 *
 * <pre>
 *      如果前台传入了别名关联。使用此工具类处理
 * </pre>
 *
 * @author wangg
 * @date 2021/7/1613:14
 */
public class AliasesUtils {

    /**
     *
     *
     * <pre>
     *     处理关联别名的数据
     * </pre>
     *
     * @param aliases 关联别名
     * @param records 原始数据集合
     * @param serviceBeans {@link ServiceBeans}
     * @param log {@link Logger}
     */
    public static void fullAliases(
            Map<String, List<String>> aliases,
            List<Map<String, Object>> records,
            ServiceBeans serviceBeans,
            Logger log) {
        if (null != aliases && !records.isEmpty()) {
            aliases.forEach(
                    (key, values) -> {
                        if (null == key
                                || !key.endsWith(Constants.END_WITH_ID)
                                || null == values
                                || values.isEmpty()) {
                            return;
                        }
                        int idx = key.lastIndexOf(Constants.END_WITH_ID);
                        String tableName = key.substring(0, idx);
                        String entityNameUncapitalized = StrUtil.toCamelCase(tableName);
                        IBasicService<
                                        ? extends AbstractEntity<? extends AbstractDTO>,
                                        ? extends AbstractDTO>
                                basicService = serviceBeans.getService(entityNameUncapitalized);
                        Map<Long, List<Map<String, Object>>> dataMaps = pageToMaps(records, key);
                        // 获取id集合
                        List<Long> ids =
                                dataMaps.keySet().stream()
                                        .filter(Objects::nonNull)
                                        .collect(Collectors.toList());
                        // 查询
                        Map<Long, ? extends AbstractDTO> resultMap =
                                basicService.findManyPropsByIds(ids, values);
                        fullData(values, entityNameUncapitalized, dataMaps, ids, resultMap, log);
                    });
        }
    }

    /**
     *
     *
     * <pre>
     *     把查询到的关联数据填充到原数据集合中
     * </pre>
     *
     * @param columnNames 关联查询的数据表字段名
     * @param entityNameUncapitalized 实体名，首字母小写
     * @param dataMaps 原数据集合整理为Map
     * @param ids 关联数据的ID
     * @param resultMap 关联到的查询数据结果
     * @param log {@link Logger}
     */
    private static void fullData(
            List<String> columnNames,
            String entityNameUncapitalized,
            Map<Long, List<Map<String, Object>>> dataMaps,
            List<Long> ids,
            Map<Long, ? extends AbstractDTO> resultMap,
            Logger log) {
        if (null != resultMap) {
            resultMap.forEach(
                    (id, entity) -> {
                        List<Map<String, Object>> maps = dataMaps.get(id);
                        for (String value : columnNames) {
                            String fieldName = StrUtil.toCamelCase(value);
                            Object fieldValue = BeanUtil.getFieldValue(entity, fieldName);
                            maps.forEach(
                                    data ->
                                            data.put(
                                                    entityNameUncapitalized + "_" + fieldName,
                                                    fieldValue));
                        }
                    });
        } else {
            if (log.isWarnEnabled()) {
                log.warn("Not Found tableName with id in " + JSONObject.toJSONString(ids));
            }
        }
    }

    /**
     *
     *
     * <pre>
     *     把原始数据集合整理为Map结构
     * </pre>
     *
     * @param records 记录集合
     * @param key 用于关联外部的字段名
     * @return map
     */
    private static Map<Long, List<Map<String, Object>>> pageToMaps(
            List<Map<String, Object>> records, String key) {
        Map<Long, List<Map<String, Object>>> dataMaps = new HashMap<>();
        records.forEach(
                it -> {
                    Object theId = it.get(StrUtil.toCamelCase(key));
                    if (null == theId) {
                        return;
                    }
                    Long id = (Long) theId;
                    if (!dataMaps.containsKey(id)) {
                        dataMaps.put(id, new ArrayList<>());
                    }
                    dataMaps.get(id).add(it);
                });
        return dataMaps;
    }
}
